#pragma once

#include "D3dUtils.hpp"

class Camera;
class Scene;
class D3dTexture;
class ParamsCamera;

namespace renderer
{

extern const uint SHADOW_MAP_CASCADE_COUNT;

extern bool g_Wireframe;
extern bool g_DiffuseTexturesEnabled;
extern bool g_NormalMappingEnabled;
extern bool g_SpecularEnabled;
extern bool g_ShadowsEnabled;
extern bool g_SpotLightShadowsEnabled;
extern bool g_PointLightShadowsEnabled;
extern bool g_PositionedLightsEnabled;
extern bool g_SkinningEnabled;

extern bool g_DrawGbufferItems;
extern bool g_DrawShadowCasterItems;
extern bool g_DrawForwardItems;
extern bool g_DrawForwardEmissiveItems;
extern bool g_DrawForwardTranslucentItems;
extern bool g_DrawForwardFresnelItems;
extern bool g_DrawForwardEnvMappingItems;
extern bool g_DrawMaterialItems;
extern bool g_DrawCustomItems;

extern bool Ambient_Enabled;
extern COLORF Ambient_Color;

extern bool DirLight_Enabled;
extern COLORF DirLight_Color;
extern VEC3 DirLight_DirToLight;
extern bool DirLight_SpecularEnabled;
extern bool g_DirLight_ShadowEnabled;
extern float g_DirLight_ShadowFactor;
extern float g_DirLight_ShadowFadeStartPercent;
extern float g_DirLight_ShadowMapDepthBias;
extern float g_DirLight_ShadowMaxDist;
extern float g_DirLight_ShadowSplitLogFactor;

extern bool DirLight_Gooch_Enabled;
extern float DirLight_Gooch_LerpFactor;
extern float DirLight_Gooch_RangeBeg, DirLight_Gooch_RangeEnd;

extern bool Bloom_Enabled;
extern bool Bloom_IsKawase;
extern uint Bloom_PassCount;
extern float Bloom_ExtentFirst, Bloom_ExtentStep;
extern VEC4 Bloom_Params;

extern VEC4 GrayscaleParams;
extern VEC4 PostprocessScale, PostprocessBias;

extern VEC2 PixelateParam;

extern float DownsamplingSampleCount;
D3dTexture * GetDitheringTexture();
void SetDitheringTexture(D3dTexture *texture); // Increases reference counter.

extern float RefractionIntensity;
extern VEC4 RefractionTexParams;
D3dTexture * GetRefractionTexture();
void SetRefractionTexture(D3dTexture *texture); // Increases reference counter.

extern MATRIX LookupTextureTransform;
extern bool LookupTextureFiltering;
D3dTexture * GetLookupTexture();
void SetLookupTexture(D3dTexture *texture); // Increases reference counter.

extern MATRIX VolumeLookupTextureTransform;
extern bool VolumeLookupTextureFiltering;
D3dTexture * GetVolumeLookupTexture();
void SetVolumeLookupTexture(D3dTexture *texture); // Increases reference counter.

extern bool ComponentDecompositionEnabled;
extern VEC3 ComponentDecompositionA, ComponentDecompositionB, ComponentDecompositionC;

// How much percent of the current image will remain after a second.
// 0.f means disabled.
extern float FeedbackFactor;
extern MATRIX FeedbackTransform;

extern bool EdgeDetection_Enabled;
extern COLORF EdgeDetection_Color;
extern float EdgeDetection_Size;
extern float EdgeDetection_DepthFactor;

extern bool Fog_Enabled;
extern COLORF Fog_Color;
extern float Fog_BegPercent, Fog_EndPercent;


void Initialize();
void Finalize();

void RenderScene(Scene &scene, const Camera &camera);
// Informs that there was dramatic change in the image and/or point of view so
// last image should not remain e.g. in Feedback effect.
void Discontinuity();

void RenderSingleColorSky(const ParamsCamera &camera, const COLORF &color);

struct FRAME_STATS
{
	uint ObjectsInCamera;
	uint RenderedItems;
	uint ShadowMapRenderedItems, GbufferRenderedItems, ForwardRenderedItems;
	uint RenderedPointLights;
	uint RenderedSpotLights;
	uint RenderedShadowMapSurfaces;
};

uint GetLastFrameIndex();
void GetLastFrameStats(FRAME_STATS &outStats);
IDirect3DTexture9 * GetShadowMapTexture(uint index);
IDirect3DCubeTexture9 * GetCubeShadowMapTexture();

VEC4 CalcFogParams(const ParamsCamera &cam);

////// Ambient
bool IsAmbientEnabled();
void EnableAmbient(bool enable);
const COLORF GetAmbientColor();
void SetAmbientColor(const COLORF &v);

// Objects of this class automatically register themselves in the renderer.
// They are also automatically deleted during renderer finalization.
// Texture can be NULL. Reference counter to the texture is incremented.
class Overlay
{
public:
	bool Enabled;
	D3DBLENDOP BlendOp;
	D3DBLEND SrcBlend, DstBlend;
	VERTEX_RD2 Vertices[4];
	D3DTEXTUREADDRESS AddressU, AddressV;
	D3DTEXTUREFILTERTYPE MinFilter, MagFilter, MipFilter;

	Overlay();
	~Overlay();

	D3dTexture * GetTexture() { return m_Texture; }
	void SetTexture(D3dTexture *texture);

	void SetPositionsToFullScreen();
	void SetColors(COLOR color);
	void SetTexCoords(const RECTF &texCoords);

private:
	D3dTexture *m_Texture;
};

struct RENDER_CONTEXT_GBUFFER
{
	const ParamsCamera &Camera;
};

struct RENDER_CONTEXT_FORWARD
{
	const ParamsCamera &Camera;
};

struct RENDER_CONTEXT_SHADOW_MAP
{
	bool IsPointLight;
	const MATRIX &ViewProj;
	const VEC3 &LightPos; // Valid only if IsPointLight
	float LightRange; // Valid only if IsPointLight
};

} // namespace renderer
